<?php
declare (strict_types = 1);

namespace app\command;

use think\console\Command;
use think\console\command\make\Model;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\facade\Db;

class ModelCommand extends Model
{
    protected function configure()
    {
        // 指令配置
        $this->addArgument('name', Argument::REQUIRED, "The name of the class");
        $this->setName('model')
            ->setDescription('the model command');
    }

    protected function getStub(): string
    {
        return __DIR__ . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'model.stub';
    }

    protected function buildClass(string $name)
    {
        $stub = file_get_contents($this->getStub());

        $namespace = trim(implode('\\', array_slice(explode('\\', $name), 0, -1)), '\\');

        $class = str_replace($namespace . '\\', '', $name);

        $modelName = $this->getModelName($class);

        return str_replace(['{%className%}', '{%actionSuffix%}', '{%namespace%}', '{%app_namespace%}', '{%modelName%}', '{%fields%}'], [
            $class,
            $this->app->config->get('route.action_suffix'),
            $namespace,
            $this->app->getNamespace(),
            $modelName,
            $this->getFields($modelName),
        ], $stub);
    }

    protected function getModelName($class): string
    {
        $len = strrpos($class, 'Model');
        $modelName = substr($class, 0, $len);
        return un_camelize($modelName);
    }

    protected function getFields(string $name): string
    {
        $fieldList = Db::query('SHOW FULL COLUMNS FROM `' . $name . '`');
        $str = '';
        foreach ($fieldList as $key => $field) {
            $type = $this->getFieldType($field['Type']);
            $fieldName = camelize($field['Field']);
            $comment = $field['Comment'];
            if ($key == 0) {
                $str .= "@property {$type} " . '$' . $fieldName . " {$comment} \n";
            } elseif (isset($fieldList[$key + 1])) {
                $str .= " * @property {$type} " . '$' . $fieldName . " {$comment} \n";
            } else {
                $str .= " * @property {$type} " . '$' . $fieldName . " {$comment}";
            }
        }
        return $str;
    }

    /**
     * 获取类型
     * @param $type
     * @return string
     */
    protected function getFieldType($type): string
    {
        $type = strtolower($type);
        // int 类型
        if (strpos($type, 'tinyint') !== false) {
            return 'int';
        }
        if (strpos($type, 'smallint') !== false) {
            return 'int';
        }
        if (strpos($type, 'mediumint') !== false) {
            return 'int';
        }
        if (strpos($type, 'int') !== false) {
            return 'int';
        }
        if (strpos($type, 'bigint') !== false) {
            return 'int';
        }

        // 浮点类型
        if (strpos($type, 'float') !== false) {
            return 'float';
        }
        if (strpos($type, 'double') !== false) {
            return 'float';
        }
        if (strpos($type, 'decimal') !== false) {
            return 'float';
        }

        // 数组类型
        if (strpos($type, 'json') !== false) {
            return 'array';
        }

        // 默认字符串
        return 'string';
    }

    protected function getNamespace(string $app): string
    {
        return 'app' . ($app ? '\\' . $app : '') . '\\models';
    }
}
